﻿using Renci.SshNet;
using Renci.SshNet.Sftp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static System.Net.WebRequestMethods;

namespace LSFTP.MultithreadFileDownload
{
    public class DownLoadFile
    {
        public delegate void dlgSendMsg(DownMsg msg);
        public event dlgSendMsg doSendMsg;

        public int ThreadNum = 3;
        List<Thread> list = new List<Thread>();

        public DownLoadFile()
        {
            doSendMsg += Change;
        }

        private void Change(DownMsg msg)
        {
            if (msg.Tag == DownStatus.Error || msg.Tag == DownStatus.End)
            {
                StartDown(1);
            }
        }

        public void AddDown(string remoteFile,string localFile,SFTPClient sftp,int Id)
        {
            Thread tsk = new Thread(() =>
            {
                 download(remoteFile,localFile,sftp,Id);
            });
            list.Add(tsk);
        }

        public void StartDown(int StartNum = 3)
        {
            for(int i2 = 0; i2 < StartNum; i2++)
            {
                lock(list)
                {
                    for(int i = 0;i<list.Count;i++)
                    {
                        if (list[i].ThreadState == ThreadState.Unstarted || list[i].ThreadState == ThreadState.Suspended)
                        {
                            list[i].Start();
                            break;
                        }
                    }
                }
            }
        }

        private void download(string remoteFile,string localFile,SFTPClient client, int id = 0)
        {
            DownMsg downMsg = new DownMsg();
            try
            {
                downMsg.Id = id;
                downMsg.Tag = DownStatus.Start;
                doSendMsg(downMsg);

                SftpClient sftp = client.GetSftp();

                SftpFile ftpFile = sftp.Get(remoteFile);
                downMsg.Tag = DownStatus.GetLength;
                downMsg.Length = (ulong)ftpFile.Length;
                doSendMsg(downMsg);

                DateTime start = DateTime.Now;
                TimeSpan ts;
                using (Stream stream = System.IO.File.Create(localFile))
                {
                    if (downMsg.Length == 0)
                    {
                        downMsg.Size = 0; //下载总量
                                          // 大小为0的文件直接下载完成
                        downMsg.Tag = DownStatus.End;
                        downMsg.SpeedInfo = "0 K";
                        downMsg.SurplusInfo = "已完成";
                        doSendMsg(downMsg);

                        sftp.DownloadFile(remoteFile, stream, (size) => { });
                        return;
                    }

                    sftp.DownloadFile(remoteFile, stream, (size) =>
                    {

                        if (size != downMsg.Length)
                        {
                            ts = DateTime.Now - start;
                            if (ts.TotalMilliseconds < 250) return;
                            start = DateTime.Now;
                        }

                        //下载速度
                        if (downMsg.Size == 0)
                        {
                            downMsg.Speed = size;
                        }
                        else
                        {
                            downMsg.Speed = (float)(size - downMsg.Size)*4;

                        }
                        if (downMsg.Speed == 0)
                        {
                            downMsg.Surplus = -1;
                            downMsg.SurplusInfo = "未知";
                        }
                        else
                        {
                            downMsg.Surplus = ((downMsg.Length - downMsg.Size) / downMsg.Speed);
                        }
                        downMsg.Size = size; //下载总量

                        if (size == downMsg.Length)
                        {
                            //下载完成
                            downMsg.Tag = DownStatus.End;
                            downMsg.SpeedInfo = "0 K";
                            downMsg.SurplusInfo = "已完成";
                        }
                        else
                        {
                            //下载中
                            downMsg.Tag = DownStatus.DownLoad;


                        }



                        if (doSendMsg != null) doSendMsg(downMsg);//通知具体调用者下载进度
                    });
                }

                //downMsg.Tag = DownStatus.End;
                //doSendMsg(downMsg);
            }
            catch (Exception e)
            {
                downMsg.Id = id;
                downMsg.Length = 0;
                downMsg.Tag = DownStatus.Error;
                downMsg.ErrMessage = e.Message;
                doSendMsg(downMsg);
            }
           
        }

        public void StopDown()
        {
            lock (list)
            {
                try
                {
                    for(int i = 0; i < list.Count; i++)
                    {
                        list[i].Abort(3000);
                    }
                    list.Clear();
                }
                catch(Exception) { }
    
            }
        }
    }
}
